#include "../common.h"
#include "WifiService.h"
//wifi config
const bool openWIfi = true;
std::atomic<bool> _wifiLock(false);

WifiConfig wifiConfig("", "");

const uint16_t _waitTime = 10 * 1000; //WIFI等侍时间
const uint16_t _delayTime = 500;
uint8_t _restartTimes = 8;		//失败重启次数
const uint8_t _errorTimes = 2; //清理wificonfig 次数

//sync time config
const char *ntpServer1 = "ntp.aliyun.com";
const char *ntpServer2 = "pool.ntp.org";
const uint16_t daylightOffset_sec = 8 * 60 * 60;
const uint16_t gmtOffset_sec = daylightOffset_sec; //这里采用UTC计时，中国为东八区，就是 8*60*60

namespace _WifiService {
std::mutex _mtxWifiLock;
void wifiEvent(WiFiEvent_t event) {
	switch (event) {
	case SYSTEM_EVENT_STA_CONNECTED:
		//Serial.println("wifi connected");
		break;
	case SYSTEM_EVENT_STA_GOT_IP:
		Serial.print("wifi connected get ip :");
		Serial.println(WiFi.localIP());
		App.pWifiService->syncSystemTime();
		if (wifiConfig.errorTimes != 0 || !wifiConfig.check(WiFi.SSID().c_str(), WiFi.psk().c_str())) {
			wifiConfig.save(WiFi.SSID().c_str(), WiFi.psk().c_str());
			wifiConfig.save();
		}

		EventService::trigger(EVENT_WIFI_CONNECTED);
		break;
	case SYSTEM_EVENT_STA_DISCONNECTED:
		if (_wifiLock) {
			return;
		}
		_mtxWifiLock.lock();
		if (_wifiLock || App.pWifiService->isConnected()) {
			_mtxWifiLock.unlock();
			return;
		}
		_wifiLock = true;
		Serial.println("WiFi  disconnected");
		Serial.println("wifiLock open");
		EventService::trigger(EVENT_WIFI_CLOSE);
		App.pWifiService->restart();
		Serial.println("wifiLock close");
		_wifiLock = false;
		_mtxWifiLock.unlock();
		break;
	default:
		break;
	}
}

void event_serial_message(TaskCtx<String> *ctx) {
	if (!ctx->ctx.startsWith("smartConfig")) {
		return;
	}
	App.pWifiService->smartConfig();
}

}

void WifiService::prepare() {
	EventService::registerHandle(EVENT_SERIAL_MESSAGE, &_WifiService::event_serial_message);

	if (!openWIfi) {
		return;
	}
	_wifiLock = true;
	Serial.println("WifiService prepare");
	WiFi.disconnect(true, true);
	WiFi.mode(WIFI_MODE_APSTA);
	WiFi.onEvent(_WifiService::wifiEvent);
	wifiConfig.load();
	if (wifiConfig.isEmpty()) {
		App.pRepositoryService->remove(wifiConfig.toPath());
		if (!smartConfig()) {
			Serial.println(" 配网失败!!!!!!!!!!!!!!!!!!!!!!!");
		}
	} else {
		WiFi.begin(wifiConfig.ssid.c_str(), wifiConfig.passwd.c_str());
		//判断是否连接成功
		restart();
	}
	_wifiLock = false;
}

bool WifiService::smartConfig() {
	Serial.println("wifi smartConfig start ");
	WiFi.stopSmartConfig();
	WiFi.beginSmartConfig();
	uint8_t min = 6 * 2; //一分钟
	while (!WiFi.smartConfigDone()) {
		int retry = _waitTime / _delayTime;
		while (--retry >= 0) {
			delay(_delayTime);
			//double check
			if (WiFi.smartConfigDone()) {
				return true;
			}
			Serial.print(".");
		}
		if (min-- <= 0) {
			return false;
		}
	}
	return true;
}
void WifiService::restart() {
	Serial.println("wifi start ");
	while (!WiFi.isConnected()) {
		int retry = _waitTime / _delayTime;
		while (--retry >= 0) {
			delay(_delayTime);
			//double check
			if (WiFi.isConnected()) {
				return;
			}
		}
		Serial.print(".");
		WiFi.reconnect();
		if (--_restartTimes <= 0) {
			//出现这情况是没开路由器，先开了ESP32 ，直接重启就好了
			wifiConfig.errorTimes++;
			if (wifiConfig.errorTimes >= _errorTimes) {
				wifiConfig.clear();
			}
			wifiConfig.save();
			ESP.restart();
		}
	}
}
void WifiService::syncSystemTime() {
	configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2);
	getLocalTime(&timeinfo);
	Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
}
bool WifiService::isConnected() {
	return WiFi.isConnected();
}
